package com.cheetahs.common.exception;

import cn.hutool.core.util.StrUtil;
import com.cheetahs.common.base.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 统一异常捕获
 *
 * @author Feel
 * @date 2021/1/8 10:19
 */
@Slf4j
@ControllerAdvice
public class GlobalException {

    /**
     * 数据校验异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = BindException.class)
    @ResponseBody
    public Result bindException(BindException e) {
        log.error("数据校验出现问题:[{}]，异常类型:[{}]", e.getMessage(), e.getClass());
        BindingResult bindingResult = e.getBindingResult();
        List<ObjectError> list = bindingResult.getAllErrors();
        StringBuilder builder = new StringBuilder();
        list.forEach(x -> {
            FieldError error = (FieldError) x;
            builder.append(error.getDefaultMessage());
            builder.append("<br/>");
        });
        return Result.failure(builder.toString());
    }


    /**
     * 单个参数异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = ConstraintViolationException.class)
    @ResponseBody
    public Result constraintViolationException(ConstraintViolationException e) {
        log.error("参数异常:[{}]", e.getMessage());
        String message = e.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.joining("<br/>"));
        return Result.failure(message);
    }

    /**
     * 请求类型错误
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = HttpRequestMethodNotSupportedException.class)
    @ResponseBody
    public Result httpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
        log.error("请求类型异常:[{}]", e.getMessage());
        return Result.failure("请求类型错误");
    }


    /**
     * 运行异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(value = RuntimeException.class)
    @ResponseBody
    public Result runtimeException(RuntimeException e, HttpServletRequest request) {
        e.printStackTrace();
        log.error("runtime异常:[{}]", e.getMessage());
        String requestURI = request.getRequestURI();
        log.error("异常接口地址:[{}]", requestURI);
        return Result.failure(StrUtil.format("运行异常:{},接口地址:{}", e.getMessage(), requestURI));
    }

    /**
     * 异常
     *
     * @param e e
     * @return {@link Result}
     */
    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Result exception(Exception e, HttpServletRequest request) {
        e.printStackTrace();
        log.error("未知异常:[{}]", e.getMessage());
        String requestURI = request.getRequestURI();
        log.error("异常接口地址:[{}]", requestURI);
        return Result.failure(StrUtil.format("异常:{},接口地址:{}", e.getMessage(), requestURI));
    }
}


